unit reparaciones;
interface
uses declaraciones,archivos,Dos,crt,sysutils,repuestos;
{Menu para cargar un nuevo pedido de reparacion}
procedure MenuNuevaReparacion(var archivoPedidos:TArchPedidos;var cantidadPedidos:word);
{Menu para registrar una reparacion}
procedure MenuRegistroReparacion(var pedidos:TArchPedidos; var reparados:TArchReparacion;var repuestos:TArchRepuestos;var cantidadPedidos:word;var Faltantes:tPunFaltantes;var NoReparados:tPunNoReparado);
{Carga un pedido de reparacion en el archivo de reparaciones}
procedure CargarReparacion(var archivoPedidos:TArchPedidos;var electro:str30;var cantidadPedidos:word);
{Registra la reparacion de un pedido}
procedure RegistrarReparacion(var pedidos:TArchPedidos; var reparados:TArchReparacion;var archRepuestos:TArchRepuestos;var cantidadPedidos:word;var Faltantes:tPunFaltantes;var NoReparados:tPunNoReparado);
{Registrar un repuesto dentro del registro de reparacion}
procedure RegistrarRepuestoReparacion(var reparado:TReparacion;var orden:byte);
{graba un registro de reparacion en el archivo de reparacion}
procedure GrabarReparado(var reparados:TArchReparacion;var reparado:TReparacion);
{Devuelve el pedido mas viejo}
procedure ObtenerPedido(var pedidos:TArchPedidos;var pedido:TPedido; var existe:boolean;var orden:word);
{quita del archivo el pedido mas viejo}
procedure QuitarPedido(var pedidos:TArchPedidos;var cantidadPedidos:word;var orden:word);
{Marca un pedido sin respuestos en el archivo de pedidos}
procedure MarcarPedidoSinRepuestos(var pedidos:TArchPedidos; var orden:word);

{Devuelve un array de repuestos inicializados}
function repuestosVacios():TVecRepuestos;
{Chequea que haya stock de repuestos para realizar la reparacion}
function HayRepuestos(var archRepuestos:TArchRepuestos;var reparacion:TReparacion;var cantidadRepuestos:byte):boolean;

implementation
{Carga un pedido al final del archivo de pedidos}
procedure CargarReparacion(var archivoPedidos:TArchPedidos;var electro:str30;var cantidadPedidos:word);
var
pedidoTemporal:TPedido;
Year,Month,Day,WDay : word;
begin
	GetDate(Year,Month,Day,WDay);
	if cantidadPedidos = 0 then
	begin
		pedidoTemporal.numero := 0;
	end
	else
	begin
		seek(archivoPedidos,cantidadPedidos-1);
		read(archivoPedidos,pedidoTemporal);
		pedidoTemporal.numero:=pedidoTemporal.numero + 1
	end;
	pedidoTemporal.fecha := Year*10000+Month*100+Day;
	pedidoTemporal.eletrodomestico:=electro;
	pedidoTemporal.sinRepuestos:=false;
	write(archivoPedidos,pedidoTemporal);
    cantidadPedidos := cantidadPedidos + 1;
end;

function repuestosVacios():TVecRepuestos;
var
i:byte;
begin
	for i:=1 to 10 do
	begin
		repuestosVacios[i].codigo:=0;
		repuestosVacios[i].cantidad:=0;
		repuestosVacios[i].faltantes:=0;
		
	end;
end;
procedure RegistrarReparacion(var pedidos:TArchPedidos; var reparados:TArchReparacion;var archRepuestos:TArchRepuestos;var cantidadPedidos:word;var Faltantes:tPunFaltantes;var NoReparados:tPunNoReparado);
var
pedido:TPedido;
reparado:TReparacion;
opcion:char;
contador:byte;
Year,Month,Day,WDay : word;
existe:boolean;
orden:word;
begin
	contador:=0;
	GetDate(Year,Month,Day,WDay);
	{obtiene el pedido mas viejo que no tenga faltante de repuestos}
	ObtenerPedido(pedidos, pedido, existe,orden);
	if existe then
	begin
		reparado.numero:=pedido.numero;
		reparado.fecha:= Year*10000+Month*100+Day;
		{Inicializa el arreglo de repuestos}
		reparado.repuestos:= repuestosVacios();
		{mostrar el pedido de reparacion}
		repeat
			clrscr;
			gotoxy(4,4);
			writeln(TXT_REPARACION_TITULO);
			gotoxy(8,6);
			Writeln(TXT_REPARACION_NUMERO+WToStr(pedido.numero));
			gotoxy(8,8);
			Writeln(TXT_REPARACION_FECHA_PEDIDO+LToStr(pedido.fecha));
			gotoxy(8,10);
			Writeln(TXT_REPARACION_ELECTRO+pedido.eletrodomestico);
			gotoxy(8,12);
			if contador < MAX_REPUESTOS then
			begin
				Writeln(TXT_REGISTRAR_REPUESTO_INGRESAR);
				gotoxy(8,14);
				Writeln(TXT_VOLVER_PPAL);
				gotoxy(2,24);
				{$I-}
				opcion:=readkey;
				{$I+}
				if (upcase(opcion)='1') then
				begin
					contador := contador + 1;
					RegistrarRepuestoReparacion(reparado,contador);
				end;
			end
			else
			begin
				Writeln(TXT_REGISTRAR_REPUESTO_TOPE);
				gotoxy(8,14);
				Writeln(TXT_VOLVER_PPAL);
				gotoxy(2,24);
				{$I-}
				opcion:=readkey;
				{$I+}
			end;
		until (IOResult = 0) and (opcion=OPCION_SALIR);
		if (contador <> 0) then
		begin
			repeat
				clrscr;
				gotoxy(4,4);
				writeln(TXT_REPARACION_TITULO);
				gotoxy(8,6);
				Writeln(TXT_A_REGISTRAR_REPARACIONES_CONFIRMA);
				gotoxy(8,8);
				Writeln(TXT_SINO);
				gotoxy(8,10);
				{$I-}
				opcion:=readkey;
				{$I+}
				if upcase(opcion) = OPCION_SI then
				begin
					clrscr;
					gotoxy(4,4);
					writeln(TXT_REPARACION_TITULO);
					gotoxy(8,6);
					Writeln(TXT_REPARACION_NUMERO+WToStr(pedido.numero));
					gotoxy(8,8);
					Writeln(TXT_REPARACION_FECHA_PEDIDO+LToStr(pedido.fecha));
					gotoxy(8,10);
					Writeln(TXT_REPARACION_ELECTRO+pedido.eletrodomestico);
					gotoxy(8,12);
					if HayRepuestos(archRepuestos,reparado,contador) then
					begin
						GrabarReparado(reparados,reparado);
						QuitarPedido(pedidos,cantidadPedidos,orden);
						Writeln(TXT_A_REGISTRAR_REPARACIONES_REGISTRADA);
					end else begin
						{Aqui se debe cargar la faltante de repuestos y el los pedidos no reparados}
						Writeln(TXT_A_REGISTRAR_REPARACIONES_SIN_STOCK);
						MarcarPedidoSinRepuestos(pedidos,orden);
						CargarFaltanteRepuestos(reparado,Faltantes,NoReparados);
					end;
					cantidadPedidos:=cantidadPedidos-1;
					gotoxy(10,14);
					Writeln(TXT_CUALQUIER_TECLA);
					{$I-}
					readkey;
					{$I+}
				end;
			until (IOResult = 0) and ((upcase(opcion) = OPCION_SI) or (upcase(opcion) = OPCION_NO) );
		end;
	end else begin
		clrscr;
		gotoxy(4,4);
		Writeln(TXT_TIT_REGISTRAR_REPARACIONES);
		gotoxy(8,6);
		Writeln(TXT_A_REGISTRAR_REPARACIONES);
		gotoxy(10,8);
		Writeln(TXT_A_REGISTRAR_REPARACIONES_SIN_PEDIDOS);
		gotoxy(12,10);
		Writeln(TXT_CUALQUIER_TECLA);
		gotoxy(12,12);
		{$I+}
		opcion:=readkey;
		{$I+}
	end;
end;
procedure RegistrarRepuestoReparacion(var reparado:TReparacion;var orden:byte);
var
i:byte;
begin
	i:=0;
	repeat
	clrscr;
	gotoxy(4,4);
	writeln(TXT_REPARACION_TITULO);
	gotoxy(8,6);
	Writeln(TXT_REGISTRAR_REPUESTO_INGRESAR);
	gotoxy(8,8);
	if i = 0 then
	begin
		Writeln(TXT_REGISTRAR_REPUESTO_CODIGO);
		gotoxy(2,14);
		{$I-}
		readln(reparado.repuestos[orden].codigo);
		{$I+}
		if (IOResult = 0) then
		begin
			i := 1;
		end;	
	end
	else
	begin
		Writeln(TXT_REGISTRAR_REPUESTO_CANTIDAD);
		gotoxy(2,14);
		{$I-}
		readln(reparado.repuestos[orden].cantidad);
		{$I+}
		if (IOResult = 0) then
		begin
			i := 2;
		end;	
	end;
	until (IOResult=0) and (i = 2);
end;
procedure GrabarReparado(var reparados:TArchReparacion;var reparado:TReparacion);
var
posicion:word;
posicionEncontrada,fin:boolean;
r:TReparacion;
i:word;
begin
	posicionEncontrada:=false;
	reset(reparados);
	posicion:=0;
	LeerReparados(reparados,r,fin);
	while not posicionEncontrada and not fin do
	begin
		if (r.numero>reparado.numero) then
		begin
			posicionEncontrada:= true;
		end else begin
			posicion := posicion +1;
		end;
		LeerReparados(reparados,r,fin);
	end;
		seek(reparados,posicion);
		write(reparados,reparado);
		
	while not fin do
	begin
		posicion := posicion +1;
		LeerReparados(reparados,reparado,fin);
		seek(reparados,posicion);
		write(reparados,r);
		posicion := posicion +1;
		LeerReparados(reparados,r,fin);
		seek(reparados,posicion);
		write(reparados,reparado);
	end;
end;
function HayRepuestos(var archRepuestos:TArchRepuestos;var reparacion:TReparacion;var cantidadRepuestos:byte):boolean;
var
maxRepuestos:word;
min,medio,max:word;
encontrado,HayStock:boolean;
i:byte;
rAux:TRepuesto;
arrRepDesc:TVecRepuestosDesc;
begin
	maxRepuestos:=filesize(archRepuestos);
	i:=1;
	if not (maxRepuestos=0) then
	begin
		HayStock := true;
		repeat
			max:=maxRepuestos;
			min:=0;
			encontrado:=false;
			repeat
				medio:=(max+min) div 2;
				seek(archRepuestos,medio);
				read(archRepuestos,rAux);
				if rAux.codigo<reparacion.repuestos[i].codigo then
				begin
					min:=medio+1;
				end else if rAux.codigo>reparacion.repuestos[i].codigo then
				begin
					max:=medio-1;
				end else begin
					encontrado:=true;
				end;
			until encontrado or (min>max);
			{Si se encontro el repuesto}
			if encontrado then
			begin
				if rAux.stock>=reparacion.repuestos[i].cantidad then
				begin
					arrRepDesc[i].orden := medio;
					arrRepDesc[i].faltante:=false;
					arrRepDesc[i].cantidad := rAux.stock - reparacion.repuestos[i].cantidad;
				end else begin
				{Si no hay stock se guarda la cantidad de stock que falta y marca que hay falta de un repuesto}
					{Si ya hay faltante suma toda la cantidad requerida para la reparacion}
					if rAux.faltante then
					begin
						reparacion.repuestos[i].faltantes:=reparacion.repuestos[i].cantidad;
					end else begin
						reparacion.repuestos[i].faltantes:=reparacion.repuestos[i].cantidad - rAux.stock;
					end;
					arrRepDesc[i].orden := medio;
					arrRepDesc[i].faltante:=true;
					HayStock := false;
				end;
			end else begin
				HayStock := false;
			end;
			i:=i+1;
			{Tiene que iterar todos los repuestos para marcar todos los faltantes}
		until (cantidadRepuestos < i);
	end;
	
	{Si hay stock de todos los repuestos, actualiza el mismo en el archivo de repuestos}
	if HayStock then
	begin
		i:=1;
		repeat
			seek(archRepuestos,arrRepDesc[i].orden);
			read(archRepuestos,rAux);
			rAux.stock := arrRepDesc[i].cantidad;
			seek(archRepuestos,arrRepDesc[i].orden);
			write(archRepuestos,rAux);
			i:=i+1;
		until (cantidadRepuestos < i);
	HayRepuestos:=true;
	{Si no hay suficiente stock de al menos uin repuesto devuelve falso y marca en el achivo de repuestos que 
	hay una faltante para luego }
	end else begin
		i:=1;
		repeat
			if arrRepDesc[i].faltante then
			begin
				seek(archRepuestos,arrRepDesc[i].orden);
				read(archRepuestos,rAux);
				rAux.faltante := true;
				seek(archRepuestos,arrRepDesc[i].orden);
				write(archRepuestos,rAux);
			end;
			i:=i+1;
		until (cantidadRepuestos < i);
		HayRepuestos:=false;
	end;
end;
procedure QuitarPedido(var pedidos:TArchPedidos;var cantidadPedidos:word;var orden:word);
var
i:word;
p:TPedido;
begin
	if cantidadPedidos > 0 then
	begin
		if orden < cantidadPedidos -1 then
		begin
			for i:=orden+1 to cantidadPedidos-1 do
			begin
				seek(pedidos,i);
				read(pedidos,p);
				seek(pedidos,i-1);
				write(pedidos,p);
			end;
		end else if orden = cantidadPedidos -1 then
		begin
			seek(pedidos,orden);
		end;
		truncate(pedidos);
    end	else begin
		seek(pedidos,0);
	end;
	
end;
{Obtiene un pedido que no tenga marca de sin repuestos}
procedure ObtenerPedido(var pedidos:TArchPedidos;var pedido:TPedido; var existe:boolean;var orden:word);
var
fin:boolean;
pLeido:TPedido;
begin
	orden:=0;
	seek(pedidos,0);
	repeat
		read(pedidos,pLeido);
		orden:=orden+1;
	until (not pLeido.sinRepuestos) or eof(pedidos);
	if pLeido.sinRepuestos then
	begin 
		existe:=false;
	end else begin
		existe:=true;
		pedido:=pLeido;
		orden:=orden-1;
	end;
end;
procedure MarcarPedidoSinRepuestos(var pedidos:TArchPedidos; var orden:word);
var 
pTmp:TPedido;
begin
	seek(pedidos,orden);
	read(pedidos,pTmp);
	pTmp.sinRepuestos := true;
	seek(pedidos,orden);
	write(pedidos,pTmp);
end;
procedure MenuRegistroReparacion(var pedidos:TArchPedidos; var reparados:TArchReparacion;var repuestos:TArchRepuestos;var cantidadPedidos:word;var Faltantes:tPunFaltantes;var NoReparados:tPunNoReparado);
var
opcion:char;
begin
	begin
	repeat
		clrscr;
		gotoxy(4,4);
		Writeln(TXT_TIT_REGISTRAR_REPARACIONES);
		gotoxy(8,6);
		Writeln(TXT_A_REGISTRAR_REPARACIONES);
		gotoxy(8,8);
		Writeln(TXT_VOLVER_PPAL);
		gotoxy(2,24);
		opcion:=readkey;
		if (upcase(opcion)='1') then
		begin
			if (cantidadPedidos > 0) then
			begin
				repeat
					clrscr;
					gotoxy(4,4);
					Writeln(TXT_TIT_REGISTRAR_REPARACIONES);
					gotoxy(8,6);
					Writeln(TXT_A_REGISTRAR_REPARACIONES);
					gotoxy(10,8);
					Writeln(TXT_A_REGISTRAR_REPARACIONES_INGRESO);
					gotoxy(10,12);
					Writeln(TXT_SINO);
					gotoxy(20,12);
					{$I+}
					opcion:=readkey;
					{$I+}
					if upcase(opcion)=OPCION_SI then
					begin
						RegistrarReparacion(pedidos,reparados,repuestos,cantidadPedidos,Faltantes,NoReparados);
					end;
				until (IOResult = 0) and ((upcase(opcion) = OPCION_SI) or (upcase(opcion) = OPCION_NO) );
			end else begin
				clrscr;
				gotoxy(4,4);
				Writeln(TXT_TIT_REGISTRAR_REPARACIONES);
				gotoxy(8,6);
				Writeln(TXT_A_REGISTRAR_REPARACIONES);
				gotoxy(10,8);
				Writeln(TXT_A_REGISTRAR_REPARACIONES_SIN_PEDIDOS);
				gotoxy(12,10);
				Writeln(TXT_CUALQUIER_TECLA);
				gotoxy(12,12);
				{$I+}
				opcion:=readkey;
				{$I+}
			end;
		end;
	until opcion=OPCION_SALIR;
	end;

end;
procedure MenuNuevaReparacion(var archivoPedidos:TArchPedidos;var cantidadPedidos:word);
var
electro:str30;
opcion:char;
	begin
	repeat
		clrscr;
		gotoxy(4,4);
		Writeln(TXT_TIT_REPARACIONES);
		gotoxy(8,6);
		Writeln(TXT_A_REPARACIONES);
		gotoxy(8,8);
		Writeln(TXT_VOLVER_PPAL);
		gotoxy(2,24);
		opcion:=readkey;
		if upcase(opcion)=OPCION_1 then
		begin
			{Cuenta la cantidad de pedidos}
			ContarPedidos(archivoPedidos,cantidadPedidos);
			if cantidadPedidos <= MAX_PEDIDOS then
			{Hay espacio para crear pedidos de reparacion}
			begin
				repeat
					clrscr;
					gotoxy(4,4);
					Writeln(TXT_TIT_REPARACIONES);
					gotoxy(8,6);
					Writeln(TXT_A_REPARACIONES);
					gotoxy(10,8);
					Writeln(TXT_A_REPARACIONES_INGRESO);
					gotoxy(2,14);
					{$I-}
					readln(electro);
					{$I+}
				until (IOResult=0);
				CargarReparacion(archivoPedidos,electro,cantidadPedidos);
			end
			else
			{No se puede crear un nuevo registro de reparacion}
			begin
			repeat
				clrscr;
				gotoxy(4,4);
				Writeln(TXT_TIT_REPARACIONES);
				gotoxy(8,6);
				Writeln(TXT_INFO_REPARACIONES_NO_ESPACIO);
				gotoxy(8,8);
				Writeln(TXT_VOLVER_PPAL);
				gotoxy(2,24);
				{$I+}
				opcion:=readkey;
				{$I+}
			until ((IOResult=0) and (opcion = OPCION_SALIR));
			end;
		end;
	until opcion=OPCION_SALIR;
	end;
	end.
